package net.lgy.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import net.lgy.controller.req.*;
import net.lgy.dto.*;
import net.lgy.enums.BizCodeEnum;
import net.lgy.interceptor.LoginInterceptor;
import net.lgy.model.AccountFileDO;
import net.lgy.service.AccountFileService;
import net.lgy.service.AccountService;
import net.lgy.service.FileChunkService;
import net.lgy.util.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;


@RestController
@RequestMapping("/api/file/v1")
@Tag(name = "文件管理接口", description = "提供文件列表查询、文件夹创建等文件管理功能")
@Slf4j
public class AccountFileController {

    @Autowired
    private AccountFileService accountFileService;
    @Autowired
    private FileChunkService fileChunkService;
    @Autowired
    private AccountService accountService;



    /**
     * 查询文件列表接口
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @Operation(summary = "查询文件列表", description = "根据父文件夹ID查询当前用户的文件列表")
    public JsonData list(
            @RequestParam(value = "parent_id", required = false)
            @Parameter(description = "父文件夹ID，根目录可传0", required = true)
            Long parentId) {

        // 增加参数校验日志
        log.info("查询文件列表，parentId: {}", parentId);


        try {
            Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
            // 校验用户是否已登录
            if (accountNo == null) {
                return JsonData.buildError("用户未登录");
            }

            // 增加非空校验
            if (parentId == null) {
                String phone = LoginInterceptor.threadLocal.get().getPhone();
                parentId = findParentIdByPhone(phone,accountNo);

            }


            List<AccountFileDTO> list = accountFileService.listFile(accountNo, parentId);
            log.info("查询文件列表成功，数量: {}", list.size());
            return JsonData.buildSuccess(list);
        } catch (Exception e) {
            log.error("查询文件列表异常", e);
            return JsonData.buildError("查询文件列表失败");
        }
    }


    /**
     * 创建文件夹
     */
    @PostMapping("/create_folder")
    @Operation(summary = "创建文件夹", description = "在指定父文件夹下创建新文件夹")
    public JsonData createFolder(
            @RequestBody
            @Parameter(description = "文件夹创建请求参数，包含文件夹名称和父文件夹ID", required = true)
            FolderCreateReq req) {

        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        req.setAccountNo(accountNo);
        Long folder = accountFileService.createFolder(req);

        return folder != null ? JsonData.buildSuccess():JsonData.buildError("创建失败");
    }


//    文件/文件夹重命名
    @PostMapping("/rename_file")
    @Operation(summary = "文件/文件夹重命名", description = "重命名文件/文件夹")
    public JsonData renameFile(@RequestBody FileUpdateRequest request){

        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = accountFileService.renameFile(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("重命名失败");
    }



//    文件树查询接口
    @GetMapping("/folder_tree")
    @Operation(summary = "文件树查询接口", description = "查询当前用户的文件树")
    public JsonData folderTree(){
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        List<FolderTreeNodeDTO> list = accountFileService.folderTree(accountNo);
        return JsonData.buildSuccess(list);
    }

//    小文件上传接口
    @PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "小文件上传接口", description = "上传文件接口")
    public JsonData fileUpload(@ModelAttribute FileUploadRequest request){


        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);

        //        先看看你有没有这么多剩余空间
        boolean StorageEnough = checkAndUpdateCapacity(accountNo,request.getFileSize());
        if (!StorageEnough){
//            不够存储空间
            return JsonData.buildResult(BizCodeEnum.FILE_STORAGE_NOT_ENOUGH);
        }


        Boolean result = accountFileService.fileUpload(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("上传失败");
    }

    private boolean checkAndUpdateCapacity(Long accountNo, Long fileSize) {
        return accountFileService.checkAndUpdateCapacity(accountNo,fileSize);
    }


    //    文件批量移动
    @PostMapping("/move_batch")
    @Operation(summary = "文件批量移动", description = "批量移动文件")
    public JsonData moveBatch(@Parameter(description = "文件批量移动请求参数，包含文件ID列表和目标文件夹ID", required = true)
                              @RequestBody FileBatchRequest request){
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = accountFileService.moveBatch(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("移动失败");

    }


//    文件批量删除
    @PostMapping("/delete_batch")
    @Operation(summary = "文件批量删除", description = "批量删除文件")
    public JsonData deleteBatch(@Parameter(description = "文件批量删除请求参数，包含文件ID列表", required = true)
                                @RequestBody FileDelRequest request) {
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = accountFileService.deleteBatch(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("删除失败");
    }


//    文件复制
    @PostMapping("/copy_batch")
    @Operation(summary = "文件复制", description = "批量复制文件")
    public JsonData copyBatch(@Parameter(description = "文件批量复制请求参数，包含文件ID列表和目标文件夹ID", required = true)
                              @RequestBody FileBatchRequest request) {
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = accountFileService.copyBatch(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("复制失败");
    }


//    文件秒传接口
    @PostMapping("/second_upload")
    @Operation(summary = "文件秒传接口", description = "秒传接口")
    public JsonData SecondBatch(@Parameter(description = "文件批量复制请求参数，包含文件ID列表和目标文件夹ID", required = true)
                              @RequestBody FileSecondUploadRequest request) {
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = accountFileService.SecondBatch(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("文件不存在或未达秒传条件");
    }










//    ============================分片上传任务接口开发完毕=====================================

//    创建分片上传业务
    @PostMapping("/init_file_chunk_task")
    @Operation(summary = "创建分片上传任务接口", description = "创建分片上传任务接口")
    public JsonData initFileChunkTask(@Parameter(description = "分片上传任务参数", required = true)
                                      @RequestBody FileChunkinitTaskRequest request){
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);

        FileChunkDTO fileChunkDTO = fileChunkService.initFileChunkTask(request);

        return JsonData.buildSuccess(fileChunkDTO);
    }


//    获取分片上传地址,返回minio临时签名地址
    @GetMapping("/get_file_chunk_upload_url/{identifier}/{partNumber}")
    @Operation(summary = "获取分片上传地址接口", description = "获取分片上传地址接口")
    public JsonData getFileChunkUploadUrl(@PathVariable("identifier")String identifier,
                                          @PathVariable("partNumber")int partNumber){

        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        String url = fileChunkService.getFileChunkUploadUrl(accountNo,identifier,partNumber);
        return JsonData.buildSuccess(url);
    }


//    合并分片
    @PostMapping("/merge_file_chunk")
    @Operation(summary = "合并分片接口", description = "合并分片接口")
    public JsonData mergeFileChunk(@Parameter(description = "合并分片请求参数", required = true)
                                   @RequestBody FileChunkMergeRequest request){
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        Boolean result = fileChunkService.mergeFileChunk(request);
        return result ? JsonData.buildSuccess() : JsonData.buildError("合并失败");


    }



//    查询分片上传进度接口
    @GetMapping("/chunk_upload_progress/{identifier}")
    @Operation(summary = "查询分片上传进度接口", description = "查询分片上传进度接口")
    public JsonData chunkUploadProgress(@PathVariable("identifier")String identifier){
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        FileChunkDTO fileChunkDTO = fileChunkService.listFileChunk(accountNo,identifier);
        return JsonData.buildSuccess(fileChunkDTO);
    }


    /**
     * 根据关键词搜索文件
     * 接收前端传入的搜索关键词，查询当前登录用户名下文件名包含该关键词的文件列表
     *
     * @param search 搜索关键词，用于模糊匹配文件名
     * @return JsonData 包含搜索结果的响应对象，成功时返回文件列表，失败时返回错误信息
     */
    @GetMapping("/search")
    @Operation(summary = "根据关键词搜索文件",
            description = "搜索当前登录用户名下文件名包含指定关键词的文件，支持模糊匹配，返回未删除的文件列表")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "查询成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "500", description = "查询失败（如数据库异常）",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    public JsonData search(
            @Parameter(description = "搜索关键词，用于模糊匹配文件名", required = true, example = "工作报告")
            @RequestParam("search") String search) {
        // 从ThreadLocal中获取当前登录用户的账号ID（通过登录拦截器预先设置）
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        log.info("用户[{}]执行文件搜索，关键词：{}", accountNo, search);

        // 调用服务层方法执行查询操作
        List<AccountFileDTO> fileList = accountFileService.search(accountNo, search);

        // 根据查询结果返回相应的响应
        if (fileList != null) {
            log.info("用户[{}]文件搜索完成，匹配到{}个文件", accountNo, fileList.size());
            return JsonData.buildSuccess(fileList);
        } else {
            log.error("用户[{}]文件搜索失败，关键词：{}", accountNo, search);
            return JsonData.buildError("查询失败");
        }
    }

    /**
     * 批量获取文件下载链接
     * 接收前端传入的文件ID列表，生成对应文件的预签名下载URL，支持多文件同时下载
     *
     * @param request 包含文件ID列表的请求对象
     * @return JsonData 包含下载链接列表的响应对象，成功时返回URL列表，失败时返回错误信息
     */
    @PostMapping("/batch_download_url")
    @Operation(summary = "批量获取文件下载链接",
            description = "根据传入的文件ID列表，生成对应文件的预签名下载URL，仅支持非文件夹类型文件，URL具有时效性")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "400", description = "参数错误（如文件ID为空或包含文件夹）",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "500", description = "获取失败（如MinIO服务异常）",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    public JsonData batchDownloadUrl(
            @Parameter(description = "批量下载请求参数，包含需要下载的文件ID列表", required = true)
            @RequestBody FileBatchDownloadRequest request) {
        // 从ThreadLocal中获取当前登录用户的账号ID，并设置到请求对象中（用于权限校验）
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);
        log.info("用户[{}]请求批量获取下载链接，文件ID列表：{}", accountNo, request.getFileIds());

        // 调用服务层方法生成下载链接
        List<FileDownloadDTO> downloadList = accountFileService.batchDownloadUrl(request);

        // 根据处理结果返回相应的响应
        if (downloadList != null) {
            log.info("用户[{}]批量下载链接生成完成，共{}个有效链接", accountNo, downloadList.size());
            return JsonData.buildSuccess(downloadList);
        } else {
            log.error("用户[{}]批量下载链接获取失败", accountNo);
            return JsonData.buildError("获取失败");
        }
    }



//    用户图片上传接口
    @PostMapping("/upload_user_img")
    public JsonData uploadUserImg(@RequestPart("file") MultipartFile file){

        String url = accountFileService.ImgUpload(file);
        return url == null ? JsonData.buildError("上传失败") : JsonData.buildSuccess(url);
    }






//通过phone找parent_id
    private Long findParentIdByPhone(String phone, Long accountNo){
        AccountDTO accountDTO = accountService.queryDetail(accountNo, phone);
        return accountDTO.getRootFileId();

    }





}
